package com.mytijian.code.service;

import com.mytijian.code.dao.McodeDAO;
import com.mytijian.code.dao.dataobject.McodeDO;
import com.mytijian.code.enums.ExpireStatusEnum;
import com.mytijian.code.enums.RefundStatusEnum;
import com.mytijian.code.enums.WriteOffEnum;
import com.mytijian.code.enums.WriteOffIsSuccessEnum;
import com.mytijian.code.exceptions.MashangExceptionEnum;
import com.mytijian.code.model.Mcode;
import com.mytijian.code.model.MerchantOrder;
import com.mytijian.code.utils.CodeUtils;
import com.mytijian.exception.BizException;
import com.mytijian.utils.BeanUtil;
import com.mytijian.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * Created by shjh on 2017/9/16.
 */
@Service
public class CodeServiceImpl implements CodeService {
	private Logger logger = LoggerFactory.getLogger(CodeServiceImpl.class);

	@Autowired
	private McodeDAO mcodeDAO;
    /**
     * 通过码获取码详情
     * @param code
     * @return
     */
	@Override
	public Mcode getCodeByCode(String code){
		McodeDO mcodeDO =mcodeDAO.selectByCode(code);
		return BeanUtil.createObject(mcodeDO, Mcode.class);
	}

	@Override
	public List<Mcode> saveMcodes(MerchantOrder order) {
		return addCodes(order);
	}

	@Override
	public List<Mcode> listMcodeByOuterId(String outerId) {
		List<McodeDO> mcodeDOs = mcodeDAO.selectMcodesByOuterId(outerId);
		if (CollectionUtils.isEmpty(mcodeDOs)) {
			return new ArrayList<>();
		}
		return BeanUtil.copyBeanList(mcodeDOs, Mcode.class);
	}

	@Override
	public boolean checkCodeAvailable(Mcode code) {
		if (code == null) {
			return false;
		}
		if (code.getWriteOffStatus() != null &&code.getWriteOffStatus()) {
			return false;
		}
		if (code.getExpireStatus() != null && code.getExpireStatus()) {
			return false;
		}
		if (code.getRefundStatus() != null && code.getRefundStatus()) {
			return false;
		}
		
		return true;
	}

	@Override
	public void validCode(Mcode code) {
		if (code == null) {
			throw new BizException(MashangExceptionEnum.CODE_NOT_EXIST);
		}
		if (code.getWriteOffStatus() != null &&code.getWriteOffStatus()) {
			throw new BizException(MashangExceptionEnum.CODE_HAS_CONSUME);
		}
		if (code.getExpireStatus() != null && code.getExpireStatus()) {
			throw new BizException(MashangExceptionEnum.CODE_HAS_EXPIRED);
		}
		if (code.getRefundStatus() != null && code.getRefundStatus()) {
			throw new BizException(MashangExceptionEnum.CODE_HAS_REFUND);
		}
		checkValidEndExpired(code);
	}

	private void checkValidEndExpired(Mcode code) {
		Date end = DateUtils.parse(DateUtils.YYYY_MM_DD_HMS, code.getValidEnd());
		if (end.before(new Date())) {
			throw new BizException(MashangExceptionEnum.CODE_HAS_EXPIRED);
		}
	}

	@Override
	public int updateMcode(Mcode mcode) {
		return mcodeDAO.updateMcodeById(BeanUtil.createObject(mcode, McodeDO.class));
	}

	@Override
	public int updateMcodeByOuterId(Mcode mcode) {
		return mcodeDAO.updateMcodeByOuterId(BeanUtil.createObject(mcode, McodeDO.class));
	}

	@Override
	public List<Mcode> listNeedConsumeCode() {
		List<McodeDO> mcodeDOs = mcodeDAO.selectNeedConsumeCode();

		return BeanUtil.copyBeanList(mcodeDOs, Mcode.class);
	}

	@Override
	public void refundCodesByOrderId(String outerId) {
		McodeDO mcodeDO = new McodeDO();
		mcodeDO.setOuterId(outerId);
		mcodeDO.setRefundStatus(RefundStatusEnum.REFUND.getCode());
		mcodeDAO.updateMcodeByOuterId(mcodeDO);
	}

	private List<Mcode> addCodes(MerchantOrder order) {
		List<McodeDO> mcodeDOs = Collections.emptyList();
		for (int i = 1; i < 4 && mcodeDOs.size() == 0; i++) {
			mcodeDOs = createCodes(order);
		}
		if (mcodeDOs.size() == 0) {
			throw new BizException(MashangExceptionEnum.CREATE_CODE_ERROR);
		}

		List<Mcode> mcodes = new ArrayList<>();
		for (McodeDO mcodeDO : mcodeDOs) {
			mcodes.add(BeanUtil.createObject(mcodeDO, Mcode.class));
		}
		return mcodes;
	}

	private List<McodeDO> createCodes(MerchantOrder order) {
		List<McodeDO> mcodeDOs = new ArrayList<McodeDO>();
		try {
			for (int i = 0; i < order.getAmount(); i++) {
				mcodeDOs.add(createMcodeDO(order));
			}
			mcodeDAO.batchInsert(mcodeDOs);
		} catch (Exception ex) {
			mcodeDOs = Collections.emptyList();
			logger.warn("订单[outerId={},id={}]电子码生成异常:", order.getOuterId(), order.getId(), ex);
		}
		
		return mcodeDOs;
	}

	private McodeDO createMcodeDO(MerchantOrder tmOrder) {
		McodeDO mcodeDO = new McodeDO();
		mcodeDO.setCode(CodeUtils.createCode());
		mcodeDO.setValidStart(tmOrder.getValidStart());
		mcodeDO.setValidEnd(tmOrder.getValidEnd());
		mcodeDO.setSendStyle(tmOrder.getSendStyle());
		mcodeDO.setFrequency(tmOrder.getFrequency());
		mcodeDO.setOuterId(tmOrder.getOuterId());
		mcodeDO.setExpireStatus(ExpireStatusEnum.UNEXPIRE.getCode());
		mcodeDO.setRefundStatus(RefundStatusEnum.UNREFUND.getCode());
		mcodeDO.setWriteOffStatus(WriteOffEnum.UN_WRITE_OFF.getCode());
		mcodeDO.setWriteOffIsSuccess(WriteOffIsSuccessEnum.UN_WRITE_OFF_SUCCESS.getCode());
		return mcodeDO;
	}

}
